<template>
  <div class="app-container">
    <el-row :gutter="20">
      <el-col>
        <el-form :model="queryParams" ref="queryForm" :inline="true"  v-show="showSearch" label-width="80px">
          <el-form-item label="任务名称" prop="jobName">
            <el-input v-model="queryParams.jobName" placeholder="请输入任务名称" size="small" clearable style="width: 150px"/>
          </el-form-item>
          <el-form-item label="运行状态" prop="jobStatusCode">
            <el-select @change="handleQuery" v-model="queryParams.jobStatusCode" size="small" clearable style="width: 150px" placeholder="请选择">
              <el-option key="" label="全部" value=""/>
              <el-option
                v-for="item in jobStatusCodeList"
                :key="item.dictCode"
                :label="item.dictName"
                :value="item.dictCode"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="备注说明" prop="remark">
            <el-input v-model="queryParams.remark" placeholder="请输入备注说明" size="small" clearable style="width: 150px"/>
          </el-form-item>
          <el-form-item label="创建时间">
            <el-date-picker @change="handleQuery" v-model="dateRange" size="small" style="width: 240px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"/>
          </el-form-item>
          <el-form-item>
            <el-button type="primary"  size="mini" icon="el-icon-search" @click="handleQuery">搜索</el-button>
            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery('queryForm')">重置</el-button>
          </el-form-item>
        </el-form>
        <el-row :gutter="10" class="mb8">
          <el-col :span="1.5">
            <el-button type="primary"  v-hasPermi="['saveQuartzJob']"  icon="el-icon-plus" size="mini" @click="handleAdd">新增</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="success" v-hasPermi="['updateQuartzJob']"  icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate">修改</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="danger" v-hasPermi="['deleteQuartzJob']"  icon="el-icon-delete" size="mini" :disabled="single" @click="handleDelete">删除</el-button>
          </el-col>

          <el-col :span="1.5">
            <el-button type="info" v-hasPermi="['pauseQuartzJob']"  icon="el-icon-video-pause" size="mini" :disabled="single" @click="handlePauseQuartzJob">暂停</el-button>
          </el-col>

          <el-col :span="1.5">
            <el-button type="success" v-hasPermi="['resumeQuartzJob']"  icon="el-icon-video-play" size="mini" :disabled="single" @click="handleResumeQuartzJob">恢复</el-button>
          </el-col>

          <el-col :span="1.5">
            <el-button type="warning" v-hasPermi="['runOnceJob']"  icon="el-icon-caret-right" size="mini" :disabled="single" @click="handleRunOnceJob">执行一次</el-button>
          </el-col>

          <right-toolbar :showSearch.sync="showSearch" @queryTable="queryQuartzJobResList" :columns="columns"></right-toolbar>
        </el-row>
        <el-table ref="multipleTable" :stripe="true" v-loading="loading" :data="dataList" @selection-change="handleSelectionChange"
                    @sort-change='tableSortChange' :default-sort="{prop: 'sort', order: 'descending'}">
          <el-table-column type="selection" align="center" :selectable="checkSelectable"/>
          <el-table-column label="任务名称" align="left" prop="jobName"/>
          <el-table-column label="Cron表达式" align="left" prop="cronExpression"/>
          <el-table-column label="运行状态" align="left" prop="jobStatusName" width="150" >
            <template slot-scope="scope">
              <span :style="'color:'+scope.row.jobStatusColor">{{scope.row.jobStatusName}}</span>
            </template>
          </el-table-column>
          <el-table-column label="上次执行时间" align="center" prop="lastTime" sortable='custom' width="200" />
          <el-table-column label="备注说明" align="left" prop="remark" :show-overflow-tooltip="true"/>
          <el-table-column label="创建时间" align="center" prop="createTime" sortable='custom' width="200" />
          <el-table-column label="操作" align="center" width="200" class-name="small-padding fixed-width">
            <template slot-scope="scope">
              <el-button size="mini" type="text" icon="el-icon-view" @click="handleInfoView(scope.row)">任务详情</el-button>
              <el-button size="mini" type="text" icon="el-icon-s-operation" @click="handleQuartzJobLog(scope.row)">异常记录</el-button>
            </template>
          </el-table-column>
        </el-table>
        <pagination v-show="total>0"  :total="total" :page.sync="queryParams.page" :limit.sync="queryParams.rows" @pagination="queryQuartzJobResList"/>
      </el-col>
    </el-row>


    <!-- 添加或修改参数配置对话框 -->
    <el-dialog :title="title" :visible.sync="addUpdateOpen" width="800px" append-to-body>
      <el-form ref="form" :model="form" :rules="addUpdateOpenRules"  label-width="110px">
        <el-form-item label="任务名称" prop="jobName">
          <el-input :hide-required-asterisk="true" autocomplete="off" v-model="form.jobName" placeholder="请输入岗位名称" maxlength="50" />
        </el-form-item>

        <el-form-item prop="classPath">
              <span slot="label">
                任务路径
                <el-tooltip placement="top">
                  <div slot="content">
                    Class类路径示例：com.duojuhe.admin.spring.schedule.task.TestTask
                  </div>
                  <i class="el-icon-question"></i>
                </el-tooltip>
              </span>
          <el-input v-model="form.classPath" placeholder="请输入任务路径" />
        </el-form-item>

        <el-form-item label="目标方法" prop="methodName">
          <el-input autocomplete="off" v-model="form.methodName" placeholder="请输入目标方法"/>
        </el-form-item>

        <el-form-item label="SpringId" prop="springId">
          <el-input v-model="form.springId" placeholder="请输入,可留空(被Spring管理的Bean名称)"/>
        </el-form-item>

        <el-form-item label="Cron表达式" prop="cronExpression">
          <el-input v-model="form.cronExpression" placeholder="请输入Cron执行表达式">
            <template slot="append">
              <el-button type="primary" @click="handleShowCron">
                生成表达式
                <i class="el-icon-time el-icon--right"></i>
              </el-button>
            </template>
          </el-input>
        </el-form-item>

        <el-form-item label="是否同步" prop="isSyncCode">
          <el-select :hide-required-asterisk="true" v-model="form.isSyncCode" clearable placeholder="请选择"  style="width: 100%;">
            <el-option
              v-for="item in isSyncCodeList"
              :key="item.dictCode"
              :label="item.dictName"
              :value="item.dictCode"
            />
          </el-select>
        </el-form-item>

        <el-form-item label="任务描述" prop="description">
          <el-input :hide-required-asterisk="true" autocomplete="off" v-model="form.description" placeholder="请输入任务描述"/>
        </el-form-item>

      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitForm">确 定</el-button>
        <el-button @click="cancelAddUpdateOpen">取 消</el-button>
      </div>
    </el-dialog>


    <!--Cron表达式生成器-->
    <el-dialog title="Cron表达式生成器" :visible.sync="cronExpressionOpen" append-to-body destroy-on-close class="scrollbar">
      <crontab @hide="cronExpressionOpen=false" @fill="handleCronTabFill" :expression="expression"></crontab>
    </el-dialog>


    <!--调度日志-->
    <el-dialog :title="title"  :visible.sync="quartzJobLogOpen" :close-on-click-modal="false" append-to-body destroy-on-close class="scrollbar">
      <el-form :model="queryQuartzJobLogParams" ref="queryQuartzJobLogForm" :inline="true" label-width="80px">
        <el-form-item label="执行状态" prop="operationStatusCode">
          <el-select @change="handleQueryQuartzJobLog" v-model="queryQuartzJobLogParams.operationStatusCode" size="small" clearable style="width: 150px" placeholder="请选择">
            <el-option key="" label="全部" value=""/>
            <el-option
              v-for="item in operationStatusCodeList"
              :key="item.dictCode"
              :label="item.dictName"
              :value="item.dictCode"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="记录时间">
          <el-date-picker @change="handleQueryQuartzJobLog" v-model="quartzJobLogDateRange" size="small" style="width: 240px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"/>
        </el-form-item>
        <el-form-item>
          <el-button type="primary"  size="mini" icon="el-icon-search" @click="handleQueryQuartzJobLog">搜索</el-button>
          <el-button icon="el-icon-refresh" size="mini" @click="resetQueryQuartzJobLog('queryQuartzJobLogForm')">重置</el-button>
        </el-form-item>
      </el-form>
      <el-table :stripe="true" v-loading="quartzJobLogLoading" :data="quartzJobLogDataList">
        <el-table-column label="任务名称" align="left" prop="jobName"/>
        <el-table-column label="Cron表达式" align="left" prop="cronExpression"/>
        <el-table-column label="执行状态" align="left" prop="operationStatusName" width="80" >
          <template slot-scope="scope">
            <span :style="'color:'+scope.row.operationStatusColor">{{scope.row.operationStatusName}}</span>
          </template>
        </el-table-column>
        <el-table-column label="记录时间" align="center" prop="createTime" sortable='custom' width="200" />
        <el-table-column label="备注说明" align="left" prop="remark" :show-overflow-tooltip="true"/>
        <!--<el-table-column label="结果描述" align="left" prop="description" :show-overflow-tooltip="true"/>-->
      </el-table>
      <pagination v-show="quartzJobLogTotal>0"  :total="quartzJobLogTotal" :page.sync="queryQuartzJobLogParams.page" :limit.sync="queryQuartzJobLogParams.rows" @pagination="queryQuartzJobLogResList"/>
    </el-dialog>

    <!-- 任务详情弹窗 -->
    <el-dialog :title="title" :visible.sync="handleInfoViewOpen" width="800px" :close-on-click-modal="false">
      <el-form ref="form" :model="form">
        <table align="center" border="0" cellspacing="0" cellpadding="0" class="dialogModule">
          <tr>
            <td class="ContentName">任务名称</td>
            <td class="ContentValue">
              <span class="label">{{form.jobName}}</span>
            </td>
            <td class="ContentName">创建时间</td>
            <td class="ContentValue">
              <span class="label">{{form.createTime}}</span>
            </td>
          </tr>

          <tr>
            <td class="ContentName">运行状态</td>
            <td class="ContentValue">
              <span class="label">{{form.jobStatusName}}</span>
            </td>
            <td class="ContentName">备注说明</td>
            <td class="ContentValue">
              <span class="label">{{form.remark}}</span>
            </td>
          </tr>
          <tr>
            <td class="ContentName">Cron表达式</td>
            <td colspan="3" class="ContentValueMultiple">   <span class="textarea">{{form.cronExpression}}</span></td>
          </tr>
          <tr>
            <td class="ContentName">任务路径</td>
            <td colspan="3" class="ContentValueMultiple">  <span class="textarea">{{form.classPath}}</span> </td>
          </tr>
          <tr>
            <td class="ContentName">目标方法</td>
            <td class="ContentValue">
              <span class="label">{{form.methodName}}</span>
            </td>
            <td class="ContentName">SpringId</td>
            <td class="ContentValue">
              <span class="label">{{form.springId}}</span>
            </td>
          </tr>
          <tr>
            <td class="ContentName">是否同步</td>
            <td class="ContentValue">
              <span class="label">{{form.isSyncName}}</span>
            </td>
            <td class="ContentName">是否内置</td>
            <td class="ContentValue">
              <span class="label">{{form.builtInName}}</span>
            </td>
          </tr>
          <tr>
            <td class="ContentName">任务描述</td>
            <td colspan="3" class="ContentValueMultiple">   <span class="textarea">{{form.description}}</span></td>
          </tr>

          <tr>
            <td class="ContentName">上次执行时间</td>
            <td class="ContentValue">
              <span class="label">{{form.lastTime}}</span>
            </td>
            <td class="ContentName">下次执行时间</td>
            <td class="ContentValue">
              <span class="label">{{form.nextTime}}</span>
            </td>
          </tr>

        </table>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="close" @click="cancelAddUpdateOpen">关 闭</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
  import { getDicListByDictCodeList } from '@/api/common/dict'
  import {queryQuartzJobLogResList} from '@/api/quartz/quartzJobLog'
  import {queryQuartzJobResList, saveQuartzJob, updateQuartzJob, deleteQuartzJobByJobId,pauseQuartzJobByJobId,resumeQuartzJobByJobId,runOnceJobByJobId} from '@/api/quartz/quartzJob'
  import Crontab from '@/components/Crontab'

  //默认查询参数
  let defaultQueryParams = {
    jobName: undefined,
    startTime: undefined,
    endTime: undefined,
    jobStatusCode: "",
    remark: undefined,
    page: 1,
    rows: 10
  }
  export default {
    name: 'quartzJobAdmin',
    components: { Crontab },
    data() {
      return {
        // 遮罩层
        loading: true,
        // 选中数组
        ids: [],
        // 非单个禁用
        single: true,
        // 非多个禁用
        multiple: true,
        // 总条数
        total: 0,
        // 显示搜索条件
        showSearch: true,
        //操作定时任务
        dataList: [],
        //日志总条数
        quartzJobLogTotal:0,
        //日志数据集合
        quartzJobLogDataList: [],
        //日志遮罩层
        quartzJobLogLoading:true,
        // 日期范围
        quartzJobLogDateRange: [],
        //执行状态
        operationStatusCodeList:[],
        // 日志数据查询参数
        queryQuartzJobLogParams: {
          page: 1,
          rows: 10,
          startTime: undefined,
          endTime: undefined,
          jobId:undefined,
          operationStatusCode:""
        },
        // 日期范围
        dateRange: [],
        //运行状态
        jobStatusCodeList: [],
        //是否同步
        isSyncCodeList:[],
        // 弹出层标题
        title: "",
        // 是否显示新增修改弹出层
        addUpdateOpen: false,
        // 详情弹窗弹出层
        handleInfoViewOpen:false,
        // 增加修改表单参数
        form: {},
        // 是否显示Cron表达式弹出层
        cronExpressionOpen: false,
        //调度日志弹出层
        quartzJobLogOpen:false,
        // 传入的表达式
        expression: "",
        // 查询参数
        queryParams: { ...defaultQueryParams },
        //列信息
        columns: [],
        // 新增修改表单校验
        addUpdateOpenRules: {
          jobName: [
            { required: true, message: "任务名称不能为空",trigger: "blur" },
          ],
          cronExpression: [
            { required: true, message: "Cron表达式不能为空",trigger: "blur" },
          ],
          isSyncCode: [
            { required: true, message: "是否同步必须选择"},
          ],
          methodName: [
            { required: true, message: "目标方法不能为空",trigger: "blur" },
          ],
          classPath: [
            { required: true, message: "任务路径不能为空",trigger: "blur" },
          ]
        }
      }
    },
    created() {
      this.queryQuartzJobResList()
      this.initDict()
    },
    methods: {
      // 多选框选中数据
      handleSelectionChange(selection) {
        this.ids = selection.map(item => item.jobId)
        this.single = selection.length !== 1;
        this.multiple = !selection.length
      },
      //排序
      tableSortChange(column) {
        //格式化排序参数，构建中
        this.orderByFormat(this.queryParams,column);
        //执行查询方法
        this.queryQuartzJobResList()
      },

      /** 查询定时任务列表 */
      queryQuartzJobResList() {
        this.loading = true
        queryQuartzJobResList(this.addDateRange(this.queryParams, this.dateRange)).then(res => {
            this.dataList = res.data.records
            this.total = res.data.total
          }
        ).finally(() => {
          //关闭加载特效
          this.loading = false
        })
      },

      /** 查询日志 */
      queryQuartzJobLogResList() {
        this.quartzJobLogLoading = true
        queryQuartzJobLogResList(this.addDateRange(this.queryQuartzJobLogParams, this.quartzJobLogDateRange)).then(res => {
            this.quartzJobLogDataList = res.data.records
            this.quartzJobLogTotal = res.data.total
          }
        ).finally(() => {
          //关闭加载特效
          this.quartzJobLogLoading = false
        })
      },

      //获取数据字典
      initDict(){
        let dictArr = ["QUARTZ_STATUS","YES_NO",'OPERATION_STATUS'];
        getDicListByDictCodeList(dictArr).then(res => {
          this.jobStatusCodeList = JSON.parse(JSON.stringify(res.data['QUARTZ_STATUS']));
          this.isSyncCodeList = JSON.parse(JSON.stringify(res.data['YES_NO']));
          this.operationStatusCodeList = JSON.parse(JSON.stringify(res.data['OPERATION_STATUS']));
        });
      },
      // 是否允许选择
      checkSelectable(row) {
        return row.builtIn!=='YES'
      },
      //查看详情
      handleInfoView(row){
        this.reset();
        this.handleInfoViewOpen = true;
        this.title = "查看【"+row.jobName+"】详情";
        this.form = row;
      },

      //打开调度日志
      handleQuartzJobLog(row){
        this.quartzJobLogOpen = true;
        this.title = "【"+row.jobName+"】调度日志";
        this.queryQuartzJobLogParams.jobId = row.jobId?row.jobId:"undefined";
        this.queryQuartzJobLogResList();
      },

      /** 调度日志重置按钮操作 */
      resetQueryQuartzJobLog(fromId) {
        this.quartzJobLogDateRange = []
        this.resetForm(fromId)
        this.handleQueryQuartzJobLog()
      },

      /** 调度日志搜索按钮操作 */
      handleQueryQuartzJobLog() {
        this.queryQuartzJobLogParams.page = 1
        this.queryQuartzJobLogResList()
      },


      /** cron表达式按钮操作 */
      handleShowCron() {
        this.expression = this.form.cronExpression;
        this.cronExpressionOpen = true;
      },

      /** 确定后回传值 */
      handleCronTabFill(value) {
        this.form.cronExpression = value;
      },

      /** 新增按钮操作 */
      handleAdd() {
        this.reset();
        this.addUpdateOpen = true;
        this.title = "添加定时任务";
      },
      /** 修改按钮操作 */
      handleUpdate(row) {
        this.reset();
        row = row.isTrusted ? this.$refs.multipleTable.selection[0] : row;
        //修改表单填充
        this.form = {...row};
        this.addUpdateOpen = true;
        this.title = "修改定时任务";
      },
      /** 删除按钮操作 */
      handleDelete(row) {
        row = row.isTrusted ? this.$refs.multipleTable.selection[0] : row;
        this.$confirm('是否确认删除所选定时任务?', "警告", {
          cancelButtonText: "取消",
          confirmButtonText: "确定",
          type: "warning"
        }).then(function() {
          const jobId={jobId:row.jobId}
          return deleteQuartzJobByJobId(jobId);
        }).then(response => {
          this.$modal.msgSuccess(response.message)
          this.queryQuartzJobResList();
        }).catch(function() {});
      },


      /** 暂停按钮操作 */
      handlePauseQuartzJob(row) {
        row = row.isTrusted ? this.$refs.multipleTable.selection[0] : row;
        this.$confirm('是否确认暂停所选定时任务?', "警告", {
          cancelButtonText: "取消",
          confirmButtonText: "确定",
          type: "warning"
        }).then(function() {
          const jobId={jobId:row.jobId}
          return pauseQuartzJobByJobId(jobId);
        }).then(response => {
          this.$modal.msgSuccess(response.message)
          this.queryQuartzJobResList();
        }).catch(function() {});
      },

      /** 恢复按钮操作 */
      handleResumeQuartzJob(row) {
        row = row.isTrusted ? this.$refs.multipleTable.selection[0] : row;
        this.$confirm('是否确认恢复所选定时任务?', "警告", {
          cancelButtonText: "取消",
          confirmButtonText: "确定",
          type: "warning"
        }).then(function() {
          const jobId={jobId:row.jobId}
          return resumeQuartzJobByJobId(jobId);
        }).then(response => {
          this.$modal.msgSuccess(response.message)
          this.queryQuartzJobResList();
        }).catch(function() {});
      },

      /** 立即执行一次 */
      handleRunOnceJob(row) {
        row = row.isTrusted ? this.$refs.multipleTable.selection[0] : row;
        this.$confirm('是否确认执行一次所选定时任务?', "警告", {
          cancelButtonText: "取消",
          confirmButtonText: "确定",
          type: "warning"
        }).then(function() {
          const jobId={jobId:row.jobId}
          return runOnceJobByJobId(jobId);
        }).then(response => {
          this.$modal.msgSuccess(response.message)
          this.queryQuartzJobResList();
        }).catch(function() {});
      },


      /** 提交保存或修改按钮 */
      submitForm: function() {
        this.$refs["form"].validate(valid => {
          if (valid) {
            if (this.form.jobId !== undefined) {
              updateQuartzJob(this.form).then(response => {
                this.$modal.msgSuccess(response.message)
                this.queryQuartzJobResList();
                this.addUpdateOpen = false
              });
            } else {
              saveQuartzJob(this.form).then(response => {
                this.$modal.msgSuccess(response.message)
                this.queryQuartzJobResList();
                this.addUpdateOpen = false
              });
            }
          }
        });
      },


      /** 重置按钮操作 */
      resetQuery(fromId) {
        this.dateRange = []
        this.resetForm(fromId)
        this.handleQuery()
      },
      /** 搜索按钮操作 */
      handleQuery() {
        this.queryParams.page = 1
        this.queryQuartzJobResList()
      },
      // 取消修改增加弹出层按钮
      cancelAddUpdateOpen() {
        this.addUpdateOpen = false
        this.handleInfoViewOpen = false
        this.cronExpressionOpen = false
        this.quartzJobLogOpen = false
      },
      // 表单重置
      reset() {
        this.form = {
          jobId: undefined,
          jobName: undefined,
          cronExpression: undefined,
          isSyncCode: undefined,
          classPath: undefined,
          springId:undefined,
          methodName:undefined,
          description:undefined
        };
        this.resetForm('form')
      }
    }
  }
</script>
